home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 February / EnigmA AMIGA RUN 04 (1996)(G.R. Edizioni)(IT)[!][issue 1996-02][Skylink CD III].iso / earcd / dtype / fpvcd402.lha / Source / dispatch.c < prev    next >
C/C++ Source or Header  |  1995-01-22  |  11KB  |  422 lines

  1. /******************************************************************************
  2.  *
  3.  * VOC Datatype, based on the sourcecode found in OS3.1 Native Developer Kit
  4.  *
  5.  * Written by Christian Buchner
  6.  *
  7.  ******************************************************************************
  8.  * dispatch.c
  9.  */
  10.  
  11. #include "classbase.h"
  12.  
  13. /*****************************************************************************/
  14.  
  15. #define DEBUG 0
  16.  
  17. #if DEBUG
  18.  
  19. #define    DB(x)    x
  20.  
  21. #include <stdarg.h>
  22. void __stdargs Error(struct ClassBase *cb,UBYTE *Msg,...)
  23. {
  24.     va_list Arg;
  25.     struct EasyStruct Req={sizeof(struct EasyStruct),0,"VOC debug message",0,"Okay"};
  26.     va_start(Arg,Msg);
  27.     Req.es_TextFormat=Msg;
  28.     EasyRequestArgs(NULL,&Req,0,Arg);
  29.     va_end(Arg);
  30. }
  31.  
  32. #else
  33.  
  34. #define    DB(x)    
  35.  
  36. #endif
  37.  
  38.  
  39.  
  40. /*****************************************************************************/
  41.  
  42. Class *initClass (struct ClassBase * cb)
  43. {
  44.     Class *cl;
  45.     
  46.     if (cl = MakeClass (VOCDTCLASS, SOUNDDTCLASS, NULL, NULL, 0L))
  47.     {
  48.         cl->cl_Dispatcher.h_Entry = (ULONG (*)())Dispatch;
  49.         cl->cl_UserData = (ULONG) cb;
  50.         AddClass (cl);
  51.     }
  52.     
  53.     return (cl);
  54. }
  55.  
  56. /*****************************************************************************/
  57.  
  58. ULONG ASM Dispatch (REG (a0) Class * cl, REG (a2) Object * o, REG (a1) Msg msg)
  59. {
  60.     struct ClassBase *cb = (struct ClassBase *) cl->cl_UserData;
  61.     ULONG retval = 0L;
  62.     
  63.     switch (msg->MethodID)
  64.     {
  65.     case OM_NEW:
  66.         if (retval = DoSuperMethodA (cl, o, msg))
  67.         {
  68.             if (!(ConvertObjectData (cb, cl, (Object *) retval, ((struct opSet *) msg)->ops_AttrList)))
  69.             {
  70.                 CoerceMethod (cl, (Object *) retval, OM_DISPOSE);
  71.                 retval = NULL;
  72.             }
  73.         }
  74.         break;
  75.         
  76.      /* Let the superclass handle everything else */
  77.     
  78.     default:
  79.         retval = (ULONG) DoSuperMethodA (cl, o, msg);
  80.         break;
  81.     }
  82.     
  83.     return (retval);
  84. }
  85.  
  86. /*****************************************************************************/
  87.  
  88. #define GETLONG(a)   ( (*(a)) + (*(a+1)<<8) + (*(a+2)<<16) + (*(a+3)<<24) )
  89. #define GETTRIPLE(a) ( (*(a)) + (*(a+1)<<8) + (*(a+2)<<16) )
  90. #define GETWORD(a)   ( (*(a)) + (*(a+1)<<8) )
  91.  
  92. #define    SWAPW(a)    (WORD)(((UWORD)a>>8)+((((UWORD)a&0xff)<<8)))
  93. #define    SWAPU(a)    (UWORD)(((UWORD)a>>8)+((((UWORD)a&0xff)<<8)))
  94. #define    SWAPL(a)    (LONG)(((ULONG)a>>24)+(((ULONG)a&0xff0000)>>8)+(((ULONG)a&0xff00)<<8)+(((ULONG)a&0xff)<<24))
  95.  
  96.  
  97. /*****************************************************************************/
  98.  
  99. #define ID_Terminator        0
  100. #define ID_Sounddata        1
  101. #define ID_Soundcontinue    2
  102. #define ID_Silence            3
  103. #define ID_Marker            4
  104. #define ID_ASCII            5
  105. #define ID_Repeat            6
  106. #define ID_Endrepeat        7
  107. #define ID_Extended            8
  108.  
  109. /*****************************************************************************/
  110.  
  111. struct SoundInfo
  112. {
  113.     UBYTE soi_SampleRate;
  114.     UBYTE soi_Compression;
  115.     UBYTE soi_Data;
  116. };
  117.  
  118. #define VOCFORMAT_8BIT    0
  119. #define VOCFORMAT_4BIT    1
  120. #define VOCFORMAT_26BIT    2
  121. #define VOCFORMAT_2BIT    3
  122. #define VOCFORMAT_MDAC    4
  123.  
  124. struct SilenceInfo
  125. {
  126.     UWORD sil_Length;
  127.     UBYTE sil_SampleRate;
  128. };
  129.  
  130. struct ExtendedInfo
  131. {
  132.     UWORD exi_TimeConstant;
  133.     UBYTE exi_Compression;
  134.     UBYTE exi_Mode;
  135. };
  136.  
  137. #define MODE_MONO        0
  138. #define MODE_STEREO        1
  139.  
  140.  
  141. /*****************************************************************************/
  142.  
  143.  
  144. /*****************************************************************************/
  145.  
  146. BOOL ConvertObjectData (struct ClassBase * cb, Class * cl, Object * o, struct TagItem * attrs)
  147. {
  148.     LONG ErrorCode=0;
  149.     struct FileInfoBlock *fib;
  150.     struct VoiceHeader *vhdr;
  151.     STRPTR title;
  152.     LONG size;
  153.     ULONG len;
  154.     BPTR fh;
  155.     STRPTR buffer, ptr;
  156.     
  157.     UBYTE pass;
  158.     UBYTE ID;
  159.     
  160.     ULONG Memory;
  161.     ULONG SampleLength;
  162.     ULONG SampleFreq;
  163.     ULONG Frequency=10000;
  164.     UBYTE Mode=MODE_MONO;
  165.     UBYTE *Sample;
  166.     UBYTE *Dest=0;
  167.     ULONG DestLength;
  168.     
  169.     title = (STRPTR) GetTagData (DTA_Name, NULL, attrs);
  170.     
  171.     getdtattrs (cb, o,
  172.         SDTA_VoiceHeader, &vhdr,
  173.         DTA_Handle, &fh,
  174.         TAG_DONE);
  175.     
  176.     if (fh && vhdr)
  177.     {
  178.         /* Allocate a temporary file info block */
  179.         if (!(fib = (struct FileInfoBlock *) AllocMem (sizeof (struct FileInfoBlock), NULL)))
  180.         {
  181.             ErrorCode=ERROR_NO_FREE_STORE;
  182.             DB(Error(cb,"not enough memory"));
  183.         }
  184.         else
  185.         {
  186.             /* Get the size of the file */
  187.             if (ExamineFH (fh, fib))
  188.             {
  189.                 size = fib->fib_Size;
  190.             }
  191.             else
  192.             {
  193.                 Seek (fh, 0, OFFSET_END);
  194.                 size = Seek (fh, 0, OFFSET_BEGINNING);
  195.             }
  196.             
  197.             /* Free the temporary file info block */
  198.             FreeMem (fib, sizeof (struct FileInfoBlock));
  199.             
  200.             /* Buffered IO block */
  201.             if (!(buffer = AllocVec (size, NULL)))
  202.             {
  203.                 ErrorCode=ERROR_NO_FREE_STORE;
  204.                 DB(Error(cb,"not enough memory"));
  205.             }
  206.             else
  207.             {
  208.                 /* Read the whole file into the buffer */
  209.                 if (Read (fh, buffer, size) != size)
  210.                 {
  211.                     DB(Error(cb,"couldn't read %ld bytes : error=%ld", size, IoErr ()));
  212.                 }
  213.                 else
  214.                 {
  215.                     if (strncmp(buffer, "Creative Voice File\32",20))
  216.                     {
  217.                         ErrorCode=ERROR_OBJECT_WRONG_TYPE;
  218.                         DB(Error(cb,"unknown format"));
  219.                     }
  220.                     else
  221.                     {
  222.                         /* 3-Pass loop over whole VOC Sample */
  223.                         /* 1. Pass: find out highest sample rate */
  224.                         /* 2. Pass: determine length of whole sample */
  225.                         /* 3. Pass: synthesize 8-Bit sample by using */
  226.                         /*          highest samplerate */
  227.                         
  228.                         SampleFreq=0;
  229.                         SampleLength=0;
  230.                         
  231.                         for (pass=1;(!ErrorCode) && pass<=3;pass++)
  232.                         {
  233.                             /* get offset of the first data block to ptr */
  234.                             
  235.                             ptr=buffer+GETWORD(buffer+20);
  236.                             
  237.                             /* loop through cunks until end of buffer reached */
  238.                             
  239.                             while((!ErrorCode) && (ID=*ptr) && (ptr<buffer+size))
  240.                             {
  241.                                 len=GETTRIPLE(ptr+1);
  242.                                 ptr+=4;
  243.                                 
  244.                                 /* Handle the different chunks */
  245.                                 
  246.                                 switch(ID)
  247.                                 {
  248.                                     case ID_Sounddata:
  249.                                     {
  250.                                         struct SoundInfo *soi=(struct SoundInfo*)ptr;
  251.                                         /* MUST be uncompressed 8 bit PCM data */
  252.                                         if (soi->soi_Compression == VOCFORMAT_8BIT)
  253.                                         {
  254.                                             Mode=MODE_MONO;    /* Force MONO mode */
  255.                                             /* don't know whether this is correct */
  256.                                             /* missing some documentation! */
  257.                                             Frequency=1000000/(256-soi->soi_SampleRate);
  258.                                             DestLength=ScaleLength(len-sizeof(struct SoundInfo),Frequency,SampleFreq);
  259.                                             /* pass 1: Determine highest freq */
  260.                                             if (pass==1) if (Frequency>SampleFreq) SampleFreq=Frequency;
  261.                                             /* pass 2: calculate sample size */
  262.                                             if (pass==2) SampleLength+=DestLength;
  263.                                             /* pass 3: convert sample data */
  264.                                             if (pass==3) Convert(ptr+sizeof(struct SoundInfo), &Dest, DestLength, Frequency, SampleFreq, Mode);
  265.                                         }
  266.                                         else
  267.                                         {
  268.                                             ErrorCode=DTERROR_UNKNOWN_COMPRESSION;
  269.                                             DB(Error(cb,"unknown compression"));
  270.                                         }
  271.                                     }
  272.                                     break;
  273.                                     
  274.                                     case ID_Soundcontinue:
  275.                                     {
  276.                                         /* Frequency and Mode may have been */
  277.                                         /* initialized by ID_Extended */
  278.                                         DestLength=ScaleLength(len,Frequency,SampleFreq);
  279.                                         if (Mode==MODE_STEREO) DestLength/=2;
  280.                                         /* pass 1: Determine highest freq */
  281.                                         if (pass==1) if (Frequency>SampleFreq) SampleFreq=Frequency;
  282.                                         /* pass 2: calculate sample size */
  283.                                         if (pass==2) SampleLength+=DestLength;
  284.                                         /* pass 3: convert sample data */
  285.                                         if (pass==3) Convert(ptr, &Dest, DestLength, Frequency, SampleFreq, Mode);
  286.                                     }
  287.                                     break;
  288.                                     
  289.                                     case ID_Silence:
  290.                                     {
  291.                                         struct SilenceInfo *sil=(struct SilenceInfo*)ptr;
  292.                                         Frequency=1000000/(256-sil->sil_SampleRate);
  293.                                         DestLength=ScaleLength(((ULONG)(SWAPW(sil->sil_Length)+1)),Frequency,SampleFreq);
  294.                                         /* pass 2: calculate sample size */
  295.                                         if (pass==2) SampleLength+=DestLength;
  296.                                         /* pass 3: just skip (leave silent) */
  297.                                         if (pass==3) Dest+=DestLength;
  298.                                     }
  299.                                     break;
  300.                                     
  301.                                     case ID_Extended:
  302.                                     {
  303.                                         struct ExtendedInfo *exi=(struct ExtendedInfo*)ptr;
  304.                                         if (exi->exi_Compression != VOCFORMAT_8BIT)
  305.                                         {
  306.                                             ErrorCode=DTERROR_UNKNOWN_COMPRESSION;
  307.                                             DB(Error(cb,"unknown compression"));
  308.                                         }
  309.                                         else
  310.                                         {
  311.                                             if (exi->exi_Mode != MODE_MONO && exi->exi_Mode != MODE_STEREO)
  312.                                             {
  313.                                                 ErrorCode=ERROR_OBJECT_WRONG_TYPE;
  314.                                                 DB(Error(cb,"unknown type"));
  315.                                             }
  316.                                             else
  317.                                             {
  318.                                                 Mode=exi->exi_Mode;
  319.                                                 Frequency=256000000/(65536-SWAPW(exi->exi_TimeConstant));
  320.                                                 if (Mode==MODE_STEREO) Frequency/=2;
  321.                                             }
  322.                                         }
  323.                                     }
  324.                                     
  325.                                     default:
  326.                                     {
  327.                                         DB(Error(cb,"unknown chunk: %ld, Len: %ld",(long)ID,len));
  328.                                     }
  329.                                     break;
  330.                                     
  331.                                 }
  332.                                 ptr=ptr+len;
  333.                             }
  334.                             if (pass==2)
  335.                             {
  336.                                 /* sound.datatype V40 can replay */
  337.                                 /* directly from Fast RAM */
  338.                                     
  339.                                 Memory = (SuperClassBase->lib_Version>39) ?
  340.                                             MEMF_ANY : MEMF_CHIP;
  341.                                     
  342.                                 if (Sample=AllocVec(SampleLength, Memory | MEMF_CLEAR))
  343.                                 {
  344.                                     /* Fill in the voice header */
  345.                                     
  346.                                     memset(vhdr,0,sizeof(struct VoiceHeader));
  347.                                     vhdr->vh_OneShotHiSamples    = SampleLength;
  348.                                     vhdr->vh_SamplesPerSec        = SampleFreq;
  349.                                     vhdr->vh_Octaves            = 1;
  350.                                     vhdr->vh_Compression        = CMP_NONE;
  351.                                     vhdr->vh_Volume                = 64;
  352.                                     
  353.                                     /* Tell the super-class about the attributes */
  354.                                     
  355.                                     setdtattrs (cb, o,
  356.                                         DTA_ObjName,        title,
  357.                                         SDTA_Sample,        Sample,
  358.                                         SDTA_SampleLength,    SampleLength,
  359.                                         SDTA_Period,        (ULONG)(SysBase->ex_EClockFrequency*5)/SampleFreq,
  360.                                         SDTA_Volume,        64,
  361.                                         SDTA_Cycles,        1,
  362.                                         TAG_DONE);
  363.                                     
  364.                                     Dest=Sample;
  365.                                 }
  366.                                 else
  367.                                 {
  368.                                     ErrorCode=ERROR_NO_FREE_STORE;
  369.                                     DB(Error(cb,"not enough memory"));
  370.                                 }
  371.                             }
  372.                         }
  373.                     }
  374.                 }
  375.                 /* Free the buffer */
  376.                 FreeVec(buffer);
  377.             }
  378.         }
  379.     }
  380.     if (ErrorCode)
  381.     {
  382.         SetIoErr(ErrorCode);
  383.         return(FALSE);
  384.     }
  385.     return(TRUE);
  386. }
  387.  
  388.  
  389. /*****************************************************************************/
  390.  
  391. /* Convert the unsigned sample data to 8 bit signed PCM format */
  392. /* and do a time stretching if necessary                       */
  393. /* Destination pointer will be incremented                     */
  394. /* This one calls assembly routines for speed reasons          */
  395.  
  396. void Convert(UBYTE *Source, UBYTE **Dest, ULONG DestLength, ULONG SourceFreq, ULONG DestFreq, UBYTE Mode)
  397. {
  398.     if (Mode==MODE_MONO)
  399.     {
  400.         ConvertMono8(Source, *Dest, DestLength, SourceFreq, DestFreq);
  401.     }
  402.     if (Mode==MODE_STEREO)
  403.     {
  404.         ConvertStereo8(Source, *Dest, DestLength, SourceFreq, DestFreq);
  405.     }
  406.     *Dest+=DestLength;
  407. }
  408.  
  409. /*****************************************************************************/
  410.  
  411. ULONG setdtattrs (struct ClassBase * cb, Object * o, ULONG data,...)
  412. {
  413.     return (SetDTAttrsA (o, NULL, NULL, (struct TagItem *) & data));
  414. }
  415.  
  416. /*****************************************************************************/
  417.  
  418. ULONG getdtattrs (struct ClassBase * cb, Object * o, ULONG data,...)
  419. {
  420.     return (GetDTAttrsA (o, (struct TagItem *) & data));
  421. }
  422.